
#include "EFrustum.h"

namespace Eyas3D
{
	/* -------------------------------------------------------------------------- */
	EFrustum::EFrustum( CAMERA_TYPE mode, const EVector4D &pos, const EVector4D &dir,
			    const EVector4D & target, EFloat nearZ, EFloat farZ, EFloat ffov,
			    EFloat viewportWidth, EFloat viewportHeight )
		: camMode( mode ), position( pos ), direction( dir ), camTarget( target ),
		clip_z_near( nearZ ), clip_z_far( farZ ), fov( ffov ),
		viewport_width( viewportWidth ), viewport_height( viewportHeight ),
		camUp( EVector4D::UNIT_Y ), camRight( EVector4D::UNIT_X ), camLook( EVector4D::UNIT_Z ),
		mWorldToCamera( EMatrix44::IDENTITY ), mCameraToPerspective( EMatrix44::IDENTITY ),
		mPerspectiveToScreen( EMatrix44::IDENTITY )
	{
		viewport_center_X	= (viewport_width - 1) * 0.5f;
		viewprot_center_Y	= (viewport_height - 1) * 0.5f;
		aspect_ratio		= viewport_width / viewport_height;
		viewplane_width		= 2.0f;
		viewplane_height	= 2.0f / aspect_ratio;
		EFloat tan_fov_div2 = tan( Degree_TO_Radian( fov * 0.5f ) );
		view_dist = 0.5f * viewplane_width / tan_fov_div2;
		/*
		 * 设置裁减平面
		 * 裁减平面坐标是基于摄像机坐标系的
		 */
		EVector4D point = EVector4D::ZERO;
		/* 右裁减面 */
		EVector4D normalR = EVector4D( -view_dist, 0, viewplane_width * 0.5f );
		clip_plane_R = EPlane3D( point, normalR );
		/* 左裁减面 */
		EVector4D normalL = EVector4D( view_dist, 0, viewplane_width * 0.5f );
		clip_plane_L = EPlane3D( point, normalL );
		/* 上裁减面 */
		EVector4D normalT = EVector4D( 0, -view_dist, viewplane_height * 0.5f );
		clip_plane_T = EPlane3D( point, normalT );
		/* 下裁减面 */
		EVector4D normalB = EVector4D( 0, view_dist, viewplane_height * 0.5f );
		clip_plane_B = EPlane3D( point, normalB );
		/* 摄像机坐标系到透视坐标系变换矩阵, 经过矩阵变换之后需要除以w */
		mPerspectiveToScreen = EMatrix44( view_dist, 0, 0, 0,
						  0, view_dist * aspect_ratio, 0, 0,
						  0, 0, 1, 1,
						  0, 0, 0, 0 );
	}
	/* -------------------------------------------------------------------------- */
	/*
	 * void EFrustum::updateCamera()
	 * {
	 * switch(camMode)
	 * {
	 * case CAMERA_MODEL_ELUA:
	 *      {
	 *              / ** 欧拉角摄像机创建变换矩阵,需要这么做
	 *              Mcam = mt(-1) * my(-1) * mx(-1) * mz(-1)
	 *              即相机平移矩阵的逆矩阵 乘以 相机绕y,x,z轴的旋转矩阵的逆矩阵
	 *              * /
	 *              EMatrix44 mt_inv;
	 *              GetTranslateMatrix44(mt_inv, -position.x, -position.y, -position.z);
	 *              // direction各分量分别存储的是延各轴的旋转分量
	 *              EMatrix44 mx_inv;
	 *              GetRotateMatrix44X(mx_inv, -direction.x);
	 *              EMatrix44 my_inv;
	 *              GetRotateMatrix44Y(my_inv, -direction.y);
	 *              EMatrix44 mz_inv;
	 *              GetRotateMatrix44Z(mz_inv, -direction.z);
	 */

	/*
	 *              mWorldToCamera = mt_inv * my_inv * mz_inv * mz_inv;
	 *      }
	 *      break;
	 * case CAMERA_MODEL_UVN:
	 *      {
	 *              EMatrix44 mt_inv;
	 *              GetTranslateMatrix44(mt_inv, -position.x, -position.y, -position.z);
	 *              camLook				= camTarget - position;
	 */

	/*
	 *              camUp				= EVector4D::UNIT_Y;
	 *              camRight			= camUp.crossProduct(camLook);
	 *              camUp				= camLook.crossProduct(camRight);
	 */

	/*
	 *              camLook.normalize();
	 *              camRight.normalize();
	 *              camUp.normalize();
	 */

	/*
	 *              EMatrix44 mt_uvn(	camRight.x, camUp.x, camLook.x, 0,
	 *                                                      camRight.y, camUp.y, camLook.y, 0,
	 *                                                      camRight.z, camUp.z, camLook.z, 0,
	 *                                                      0			,0		, 0			,1);
	 *              mWorldToCamera = mt_inv * mt_uvn;
	 *      }
	 *      break;
	 * }
	 * }
	 */

	/* -------------------------------------------------------------------------- */
	void EFrustum::info(){
		//哪些信息
		//基础信息
		//CAMERA_TYPE mode, const EVector4D &pos, const EVector4D &dir, const EVector4D & target, EFloat nearZ, EFloat farZ, EFloat ffov, EFloat viewportWidth, EFloat viewportHeight
		/*
		 * camMode( mode ), position( pos ), direction( dir ), camTarget( target ),
		clip_z_near( nearZ ), clip_z_far( farZ ), fov( ffov ),
		viewport_width( viewportWidth ), viewport_height( viewportHeight ),
		camUp( EVector4D::UNIT_Y ), camRight( EVector4D::UNIT_X ), camLook( EVector4D::UNIT_Z ),
		mWorldToCamera( EMatrix44::IDENTITY ), mCameraToPerspective( EMatrix44::IDENTITY ),
		mPerspectiveToScreen( EMatrix44::IDENTITY )
		 */
		 printf( "camMode: %d\n", camMode );
		 printf( "position, x: %f, y: %f, z: %f\n", position.x, position.y, position.z );
		 printf( "direction, x: %f, y: %f, z: %f\n", direction.x, direction.y, direction.z );
		 printf( "camTarget, x: %f, y: %f, z: %f\n", camTarget.x, camTarget.y, camTarget.z );
		 printf( "viewport_width: %f, viewport_height: %f\n", viewport_width, viewport_height );
		 printf( "clip_z_near: %f, clip_z_far: %f\n",  clip_z_near, clip_z_far );
		//衍生信息
	}
}
